home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr48
/
ned100.zip
/
COLORS.ASC
< prev
next >
Wrap
Text File
|
1993-04-08
|
14KB
|
300 lines
Turbo Vision Palettes
Objects in Turbo Vision can be grouped into two broad classes: those which are
descendants of TView (such as TWindow or TButton), and those which are not
(such as TCollection). The difference, of course, is that objects which are
descended from TView (also called "views" or "view objects") are intended to
be displayed on the computer's screen at some point in their lifetimes. Every
descendant of TView contains a Draw method, which is executed whenever the
view needs to redraw itself. Although every view's Draw method is different,
they all share one characteristic: they call GetColor to determine what
on-screen colors to use when drawing the various parts of the view.
GetColor in turn calls GetPalette, which returns a pointer to the view's
palette. What is a palette? In Turbo Vision, a palette acts as a translation
table. In much the same way that the ASCII code maps byte values onto
characters, a view's palette maps the set of colors used by the view onto the
palette of the view's owner.
Let's look at the palette of the TLabel view as an example. (It's shown at the
end of the description of TLabel in the Turbo Vision Guide.) We see that the
palette has four entries, numbered 1 through 4. TLabel's Draw method knows
that when it wants to draw normal text, it should use color number 1. But it
doesn't know what color number 1 really is, and it doesn't care. It simply
calls GetColor (1) and uses the color that GetColor returns.
GetColor calls GetPalette, which returns a pointer to TLabel's palette. From
the values contained in the palette, GetColor determines that for TLabel,
color number 1 is equivalent to TLabel's owner's color number 7. GetColor then
calls Owner^.GetColor (7); the owner view then goes through the same
procedure, using its own palette to perform another level of translation, and
so on, until the ultimate owner is reached, which in most Turbo Vision
programs is a TApplication object (or descendant). The TApplication object is
the final color arbiter, and provides all of the views with the actual video
attributes to use.
Let's trace through the TLabel color hierarchy: We've already determined that
TLabel color number 1 maps onto its owner's color number 7. The description of
TLabel's palette in the TV Guide states that TLabel's palette maps onto the
standard dialog palette. This tells us that TLabel objects are intended to be
owned by (i.e., inserted into) TDialog objects. If we now turn to TDialog's
palette description, we see that color number 7 (called "Label Normal") is
mapped onto TDialog's owner's color number 38. Well, dialog boxes are usually
inserted into the desktop, so let's look at TDeskTop's palette. When we do
that, we see that TDeskTop doesn't have a palette; this means that TDeskTop
doesn't do any color translation--TDialog's color number 38 "falls through" to
TDeskTop's owner's palette. Well, the desktop is owned by the application, so
we've reached the end of the chain. When TLabel's Draw method wants to use
color number 1, it eventually gets told to use the application's color number
38.
TApplication's palettes are not shown in the TV Guide, but we can find them in
the file APP.PAS in the TVISION directory. TApplication actually uses one of
three different palettes, depending on whether the program is being run on a
color, black and white, or monochrome monitor. For the purposes of this
example, we'll assume that we're using a color monitor. If we locate the 38th
entry in TApplication's palette, we find that it is equal to $70. The upper
nybble of the byte gives the background color, and the lower nybble the
foreground color, according to the following table:
0 - black 4 - red 8 - dark gray C - light red
1 - blue 5 - magenta 9 - light blue D - light magenta
2 - green 6 - brown A - light green E - yellow
3 - cyan 7 - light gray B - light cyan F - white
So, we see that a normal label has black text on a light gray background. All
of the other colors may be tracked down in a similar manner.
What happens if rather than inserting a TLabel into a TDialog, we insert it
into a TWindow? Well, let's follow the mapping, again using the "Normal Text"
color: TLabel color number 1 -> TWindow color number 7 -> TApplication color
number 14, 22, or 30, depending on whether the window is a blue, cyan, or gray
window, respectively. These entries correspond to blue text on gray, blue text
on green, or white text on light gray. Obviously, none of these are the same
as the black text on light gray of a TLabel inserted into a TDialog. This
points out a universal truth of Turbo Vision palettes: If a view is designed
to be inserted into a particular type of owner view, inserting it into a
different type of owner will almost always result in a change in color.
Anyone who has played around much with Turbo Vision has encountered the
situation where a view is displayed in flashing white text on a red
background. This happens when a call to GetColor is made with a color number
that exceeds the size of the view's palette. For example, let's see what
happens when we insert a TListBox into a TWindow, rather than a TDialog.
(Note: The TV Guide says that TListBox's palette maps onto the application
palette. This is incorrect; it actually maps onto TDialog's palette.) TListBox
has a five-entry palette which maps onto entries 26 through 29 in its owner's
palette. Well, lo and behold, a TWindow has only eight entries in its
palette--obtaining the 26th entry is impossible. In this situation, GetColor
returns the flashing white on red color to signal the error.
Here is a list of all of the entries in TApplication's palette, along with the
objects that use them:
1 Background (DeskTop)
2 Text Normal (Menu)
3 Text Disabled (Menu)
4 Text Shortcut (Menu)
5 Selected Normal (Menu)
6 Selected Disabled (Menu)
7 Selected Shortcut (Menu)
8 Frame Passive (Blue Window)
9 Frame Active (Blue Window)
10 Frame Icon (Blue Window)
11 ScrollBar Page (Blue Window)
12 ScrollBar Reserved (Blue Window)
13 Scroller Normal Text (Blue Window)
14 Scroller Selected Text (Blue Window)
15 Reserved (Blue Window)
16 Frame Passive (Cyan Window)
17 Frame Active (Cyan Window)
18 Frame Icon (Cyan Window)
19 ScrollBar Page (Cyan Window)
20 ScrollBar Reserved (Cyan Window)
21 Scroller Normal Text (Cyan Window)
22 Scroller Selected Text (Cyan Window)
23 Reserved (Cyan Window)
24 Frame Passive (Gray Window)
25 Frame Active (Gray Window)
26 Frame Icon (Gray Window)
27 ScrollBar Page (Gray Window)
28 ScrollBar Reserved (Gray Window)
29 Scroller Normal Text (Gray Window)
30 Scroller Selected Text (Gray Window)
31 Reserved (Gray Window)
32 Frame Passive (Dialog)
33 Frame Active (Dialog)
34 Frame Icon (Dialog)
35 ScrollBar Page (Dialog)
36 ScrollBar Controls (Dialog)
37 StaticText (Dialog)
38 Label Normal (Dialog)
39 Label Highlight(Dialog)
40 Label Shortcut (Dialog)
41 Button Normal (Dialog)
42 Button Default (Dialog)
43 Button Selected (Dialog)
44 Button Disabled (Dialog)
45 Button Shortcut (Dialog)
46 Button Shadow (Dialog)
47 Cluster Normal (Dialog)
48 Cluster Selected (Dialog)
49 Cluster Shortcut (Dialog)
50 InputLine Normal (Dialog)
51 InputLine Selected (Dialog)
52 InputLine Arrows (Dialog)
53 History Arrow (Dialog)
54 History Sides (Dialog)
55 HistoryWindow ScrollBar page (Dialog)
56 HistoryWindow ScrollBar controls (Dialog)
57 ListViewer Normal (Dialog)
58 ListViewer Focused (Dialog)
59 ListViewer Selected (Dialog)
60 ListViewer Divider (Dialog)
61 InfoPane (Dialog)
62 Reserved (Dialog)
63 Reserved (Dialog)
What about changing colors in Turbo Vision? If all you want to do is change
the color of all instances of an object, say, by making all of your TButtons
cyan instead of green, you've got it easy. You just change the appropriate
entries in TApplication's palette (41 through 46), and you're set.
That was easy. Now, what about creating a new, unique view which is unlike any
predefined Turbo Vision objects? How will we color it? Let's say we want to
insert our new view (call it a TNewView) into a TDialog, and we want to use
two different colors, one for normal text and one for highlighted text. First,
we add two entries to TApplication's palette (numbers 64 and 65) that will
correspond to the two colors used by our new view. For the purposes of this
example, we'll say we want blue on light gray ($71) for normal text and light
green on light gray ($7A) for highlighted text (assuming a color monitor). Our
TApplication palette will now look like this:
CColor =
#$71#$70#$78#$74#$20#$28#$24#$17#$1F#$1A#$31#$31#$1E#$71#$00 +
#$37#$3F#$3A#$13#$13#$3E#$21#$00#$70#$7F#$7A#$13#$13#$70#$7F#$00 +
#$70#$7F#$7A#$13#$13#$70#$70#$7F#$7E#$20#$2B#$2F#$78#$2E#$70#$30 +
#$3F#$3E#$1F#$2F#$1A#$20#$72#$31#$31#$30#$2F#$3E#$31#$13#$00#$00 +
#$71#$7A; { <- these last two are the new entries }
We must make similar changes in the black & white and monochrome palettes, of
course. Next, since we will be inserting TNewView into a TDialog, we need to
override TDialog's GetPalette method so that it will supply GetColor with the
proper palette:
const
CNewDialog = CDialog + #64#65;
type
TNewDialog = object (TDialog)
function GetPalette: PPalette; virtual;
end;
.
.
.
function TNewDialog.GetPalette: PPalette;
const
P: String[Length (CNewDialog)] = CNewDialog;
begin
GetPalette := @P;
end;
Since we added our two new colors to the end of the standard TDialog palette,
which contains 32 entries, they will be the 33rd and 34th entries in
TNewDialog's palette. Now we have to define our TNewView so that it maps onto
the 33rd and 34th entry of its owner's palette:
const
CNewView = #33#34;
type
TNewView = object (TView)
function GetPalette: PPalette; virtual;
.
.
.
end;
function TNewView.GetPalette: PPalette;
const
P: String[Length (CNewView)] = CNewView;
begin
GetPalette := @P;
end;
There. That wasn't so bad, was it? When TNewView's Draw method asks for color
number 1, it will get color number 64 from TApplication's palette; similarly,
color number 2 leads to TApplication's color number 65. If we ever want to
change the colors of our TNewView object, we simply change the entries in
TApplication's palette.
Okay, let's try something a bit trickier. Let's say we want to insert a view
into an owner which is not of the "correct" type. We already know that unless
we modify the palettes and associated methods, the colors will come out wrong.
The most general solution to the problem is to define a new object type, as in
the previous example. Thus, if we wanted to insert a TButton into a TWindow,
we would define a descendant of TButton (called TWindowButton, perhaps) and
follow the same steps we performed above to give it a set of colors to use.
In some cases, we don't need to add to TApplication's palette. In the previous
example, if all we want to do is put a button in a window, and we want the
button to look just like an ordinary TButton inserted into a TDialog, we can
use the same TApplication palette entries (41 through 46):
const
CNewWindow = CGrayWindow + #41#42#43#44#45#46;
CWindowButton = #9#10#11#12#13#13#13#14;
type
TNewWindow = object (TWindow)
function GetPalette: PPalette; virtual;
end;
TWindowButton = object (TButton)
function GetPalette: PPalette; virtual;
end;
The GetPalette method code is analogous to that of the previous example. Now,
when TWindowButton.Draw asks for color number 2, it is mapped to TNewWindow's
color number 10, which is mapped to TApplication's color number 42, just as if
it had been a TButton inserted into a TDialog. Note that I used CGrayWindow as
the basis for CNewWindow's palette. Since a TButton is normally inserted into
a TDialog, two of its colors (44 and 46) use a gray background. If you wanted
to put buttons into cyan or blue windows, you would need to use the more
general method of adding to TApplication's palette, as in the previous
example.
Last but not least, what about objects which can be instantiated with one of
several palettes? TWindow is a good example of this type of object; you can
have windows with blue, gray, or cyan color schemes. One of TWindow's fields
(Palette) is used to indicate which color scheme GetPalette should return.
TWindow.GetPalette might look something like this:
function TWindow.GetPalette: PPalette;
const
PGray: string[Length (CGrayWindow)] = CGrayWindow;
PCyan: string[Length (CCyanWindow)] = CCyanWindow;
PBlue: string[Length (CBlueWindow)] = CBlueWindow;
begin
case Palette of
wpGrayWindow: GetPalette = @PGray;
wpCyanWindow: GetPalette = @PCyan;
wpBlueWindow: GetPalette = @PBlue;
end;
end;
You can use the same technique with any objects of your own devising.
Well, that's about it for Turbo Vision palettes. Are you thoroughly confused
yet? Just remember: figuring out what color a view is going to be drawn with
is as simple as tracing the color mapping up the ownership hierarchy, until
you reach the TApplication object.
Please direct comments or suggestions to Steve Schafer [71121,1771].